package cn.jinjimi.app;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;

import cn.jinjimi.app.controller.event.LoginSuccessEvent;
import cn.jinjimi.app.controller.event.LogoutEvent;
import cn.jinjimi.base.util.StringUtils;
import cn.jinjimi.app.controller.UserController;
import cn.jinjimi.app.controller.event.AnonymousEvent;
import cn.jinjimi.app.entity.Account;
import cn.jinjimi.app.entity.UserProfiles;

import org.greenrobot.eventbus.EventBus;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Set;

/**
 *
 * @author long
 * @date 14-12-18
 * 帐号管理者
 */
public final class AccountManager {
    private static SharedPreferences mSpf;
    private static Account mAccount = null;
    private static AccountManager mInstance;
    private static WeakReference<Context> mContextRef;

    public static void init(Context context) {
        mContextRef = new WeakReference<>(context);
    }

    public static Context getContext() {
        Context context = mContextRef != null ? mContextRef.get() : null;
        return context != null ? context : AppContext.getInstance();
    }

    private AccountManager() {
        mSpf = PreferenceManager.getDefaultSharedPreferences(getContext());
        mAccount = getAccountFromCache();
    }

    public static AccountManager getInstance() {
        if (mInstance == null) {
            mInstance = new AccountManager();
        }
        return mInstance;
    }

    public synchronized Account getAccount() {
        return mAccount;
    }

    public String getToken() {
        return getAccount().token;
    }

    public void setToken(String token) {
        updateAccount(NameKey.TOKEN, token);
        EventBus.getDefault().post(new LoginSuccessEvent(token));
    }

    /**
     * 更新用户单条信息
     * 同时更新缓存在内存上的和文件上的
     *
     * @param key
     * @param v
     */
    public synchronized void updateAccount(NameKey key, Object v) {
        updateAccountItem(key, v);
        saveAccountItem(key, v);
    }

    /**
     *  替换内存中的信息
     */
    private void updateAccountItem(NameKey key, Object v) {
        switch (key) {
            case SSOID:
                mAccount.ssoid = (String) v;
                break;
            case REALNAME:
                mAccount.realName = (String) v;
                break;
            case MOBILE:
                mAccount.mobile = (String) v;
                break;
            case TOKEN:
                mAccount.token = (String) v;
                break;
            case ISVIP:
                mAccount.isVip = (String) v;
                break;
            case AVATAR:
                mAccount.avatar = (String) v;
                break;
            case GENDER:
                mAccount.gender = (Integer) v;
                break;
            case CITYID:
                mAccount.cityId = (String) v;
                break;
            case CITYNAME:
                mAccount.cityName = (String) v;
                break;
            case PROVINCEID:
                mAccount.provinceId = (String) v;
                break;
            case PROVINCENAME:
                mAccount.provinceName = (String) v;
                break;
            case QQ:
                mAccount.qq = (String) v;
                break;
            case TAGS:
                mAccount.tags = (String) v;
                break;
            case UUID:
                mAccount.uuid = (String) v;
                break;
            case WEIXIN:
                mAccount.weixin = (String) v;
                break;
            default:
                break;
        }
    }

    /**
     *  判断是否已经登录
     */
    public boolean isLogin() {
        return StringUtils.isNotEmpty(getAccount().token);
    }

    /**
     *  用户登出，清除所有sp中的数据
     */
    public synchronized void logout() {
        String uuid = mAccount.uuid;

        SharedPreferences.Editor editor = mSpf.edit();
        editor.clear();
        editor.putString(NameKey.UUID.getName(), uuid);
        editor.apply();

        mAccount = getAccountFromCache();

        //匿名用户登录通知
        EventBus.getDefault().post(new AnonymousEvent());
        EventBus.getDefault().post(new LogoutEvent());
    }

    /**
     * 获取用户详情保存至本地
     *
     * @param profiles
     */
    public synchronized void setLocalProfilesForLoadProfiles(UserProfiles profiles) {
        if (profiles == null) {
            return;
        }
        HashMap<NameKey, Object> info = new HashMap<NameKey, Object>();
        if (!TextUtils.isEmpty(profiles.getSsoId())) {
            mAccount.ssoid = profiles.getSsoId();
            info.put(NameKey.SSOID, profiles.getSsoId());
        }
        if (!TextUtils.isEmpty(profiles.getRealName())) {
            mAccount.realName = profiles.getRealName();
            info.put(NameKey.REALNAME, profiles.getRealName());
        }
        if (!TextUtils.isEmpty(profiles.getPhone())) {
            mAccount.mobile = profiles.getPhone();
            info.put(NameKey.MOBILE, profiles.getPhone());
        }

        mAccount.provinceName = profiles.getProvinceName();
        info.put(NameKey.PROVINCENAME, profiles.getProvinceName());

        mAccount.gender = profiles.getGender();
        info.put(NameKey.GENDER, profiles.getGender());

        mAccount.cityId = profiles.getCityId();
        info.put(NameKey.CITYID, profiles.getCityId());

        mAccount.cityName = profiles.getCityName();
        info.put(NameKey.CITYNAME, profiles.getCityName());

        mAccount.provinceId = profiles.getProvinceId();
        info.put(NameKey.PROVINCEID, profiles.getProvinceId());

        mAccount.tags = profiles.getTagStrings();
        info.put(NameKey.TAGS, profiles.getTagStrings());

        mAccount.isVip = String.valueOf(profiles.getIsVip());
        info.put(NameKey.ISVIP, String.valueOf(profiles.getIsVip()));

        if (profiles.getAvatar_map() != null) {
            if (profiles.getAvatar_map().getSmall_header_image() != null) {
                info.put(NameKey.AVATAR, profiles.getAvatar_map().getSmall_header_image().getFile_url());
                mAccount.avatar = profiles.getAvatar_map().getSmall_header_image().getFile_url();
            }
        }
        mAccount.qq = profiles.getQq();
        info.put(NameKey.QQ, profiles.getQq());

        mAccount.weixin = profiles.getWx_no();
        info.put(NameKey.WEIXIN, profiles.getWx_no());

        saveAccount2Cache(info);
    }

    /**
     *  把用户信息保存在本地缓存文件
     */
    private void saveAccount2Cache(HashMap<NameKey, Object> hashMap) {
        if (hashMap == null || hashMap.isEmpty()) {
            return;
        }

        Set keys = hashMap.keySet();
        for (Object k : keys) {
            NameKey key = (NameKey) k;
            Object v = hashMap.get(key);
            saveAccountItem(key, v);
        }
    }

    /**
     *  保存一条数据
     */
    private void saveAccountItem(NameKey key, Object v) {

        SharedPreferences.Editor editor = mSpf.edit();

        if (v instanceof String) {
            if (needCache(key, (String) v)) {
                editor.putString(key.getName(), (String) v);
            }
        } else if (v instanceof Integer) {
            if (needCache(key, (Integer) v)) {
                editor.putInt(key.getName(), (Integer) v);
            }
        } else if (v instanceof Boolean) {
            editor.putBoolean(key.getName(), (Boolean) v);
        } else if (v instanceof Long) {
            editor.putLong(key.getName(), (Long) v);
        } else if (v instanceof Float) {
            editor.putFloat(key.getName(), (Float) v);
        } else if (v instanceof Double) {
            editor.putString(key.getName(), v.toString());
        } else if (v instanceof BigDecimal) {
            editor.putString(key.getName(), v.toString());
        }
        editor.apply();
    }

    /**
     *  判断是否需要缓存
     */
    private boolean needCache(NameKey key, String value) {
        return true;
    }

    /**
     * 判断是否需要缓存
     */
    private boolean needCache(NameKey key, int value) {
        return true;
    }

    /**
     *  读取本地缓存的用户信息
     */
    private Account getAccountFromCache() {
        Account account = new Account();
        account.realName = mSpf.getString(NameKey.REALNAME.getName(), "");
        account.mobile = mSpf.getString(NameKey.MOBILE.getName(), "");
        account.token = mSpf.getString(NameKey.TOKEN.getName(), "");
        account.ssoid = mSpf.getString(NameKey.SSOID.getName(), "");
        account.isVip = mSpf.getString(NameKey.ISVIP.getName(), "");
        account.avatar = mSpf.getString(NameKey.AVATAR.getName(), "");
        account.gender = mSpf.getInt(NameKey.GENDER.getName(), 0);
        account.tags = mSpf.getString(NameKey.TAGS.getName(), "");
        account.cityId = mSpf.getString(NameKey.CITYID.getName(), "");
        account.cityName = mSpf.getString(NameKey.CITYNAME.getName(), "");
        account.provinceId = mSpf.getString(NameKey.PROVINCEID.getName(), "");
        account.provinceName = mSpf.getString(NameKey.PROVINCENAME.getName(), "");
        account.qq = mSpf.getString(NameKey.QQ.getName(), "");
        account.uuid = mSpf.getString(NameKey.UUID.getName(), "");
        account.weixin = mSpf.getString(NameKey.WEIXIN.getName(), "");

        return account;
    }

    /**
     *  判断是否为新用户或者新升级用户
     */
    public boolean isNewAccount() {
        return false;
    }

    /**
     *  判断是否为升级用户
     */
    public boolean isUpdateAccount() {
        return false;
    }

    /**
     * 用户信息缓存文件中
     * 各属性对应的key
     */
    public enum NameKey {

        REALNAME("skey_read_name"),

        MOBILE("skey_phone"),

        TOKEN("token"),

        SSOID("skey_uid"),

        ISVIP("is_vip"),

        AVATAR("avatar"),

        GENDER("gender"),

        TAGS("tags"),

        CITYID("cityId"),

        CITYNAME("cityName"),

        PROVINCEID("provinceId"),

        PROVINCENAME("provinceName"),

        QQ("qq"),

        UUID("uuid"),

        WEIXIN("weixin");

        private String name;

        NameKey(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }
    }

}